package similan.br18.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import org.apache.commons.lang.StringUtils;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;

import similan.br18.domain.Contact;
import similan.br18.domain.Group;
import similan.br18.domain.TagType;
import similan.br18.service.ContactService;
import similan.br18.service.GroupService;
import similan.br18.util.ContactComparator;

@ManagedBean
@ViewScoped
public class ContactPanelView implements Serializable{

	private static final long serialVersionUID = 8311821757222783516L;
	
	private Map<TagType, List<Group>> cachedGroups = new HashMap<TagType, List<Group>>();
	private Map<Character, List<Contact>> groupedContacts = new HashMap<Character, List<Contact>>();
	private String selectedTableClientId;
	
	@ManagedProperty("#{groupService}")
	private transient GroupService groupService;
	
	@ManagedProperty("#{contactService}")
	private transient ContactService contactService;
	
	private Contact selectedContact;
	
	private String filterString;
	
	private Group selectedGroup;

	public void selectContact(SelectEvent event){
		if(selectedTableClientId != null){
			RequestContext.getCurrentInstance().update(selectedTableClientId);
		}
		selectedTableClientId = event.getComponent().getClientId();
	}
	
	public List<Group> getGroupsByTag(Contact contact, TagType tagType) {
		
		if(tagType == null)
			return null;
		
		if(cachedGroups.get(tagType) == null){
			List<Group> groups = groupService.getGroupsBy(contact, tagType);
			cachedGroups.put(tagType, groups);
		}
		return cachedGroups.get(tagType);
	}
	
	public void getAllContacts(Contact contact){
		setSelectedGroup(null);
		filterByText(contact);
	}
	
	public String getTagsByContact(Contact contact) {
		List<Group> groups = getGroupsByTag(contact, TagType.TAGS);

		String tags = "";

		int i = 1;
		for (Group group : groups) {
			tags += group.getName();
			if (i != groups.size()) {
				tags += ", ";
			}
			i++;
		}

		return tags;
	}
	
	public void filterByText(Contact contact) {
		List<Contact> filteredContacts = contactService
				.getContactsByGroupAndFilterText(contact, selectedGroup,
						filterString);
		Collections.sort(filteredContacts, ContactComparator.INSTANCE);

		groupContacts(filteredContacts);
	}
	
	public void filterBySubGroup(Contact contact, Group group){
		this.selectedTableClientId = null;
		this.selectedContact = null;
		List<Contact> filteredContacts = contactService.getContactsByGroup(contact, group);
		Collections.sort(filteredContacts, ContactComparator.INSTANCE);
		
		groupContacts(filteredContacts);
	}
	
	private void groupContacts(List<Contact> filteredContacts){
		groupedContacts = new TreeMap<Character, List<Contact>>();
		for (Contact contact : filteredContacts) {
			Character firstLetter = contact.getFirstLetter();
			List<Contact> groupedContactList = groupedContacts.get(firstLetter);
			
			if(groupedContactList == null){
				groupedContactList = new ArrayList<Contact>();
				groupedContacts.put(firstLetter, groupedContactList);
			}
			groupedContactList.add(contact);
		}
		
		RequestContext.getCurrentInstance().execute("charList=new Array(" + getCharList(groupedContacts) + ");");
	}
	
	private String getCharList(Map<Character, List<Contact>> groupedContacts) {
		return "'"
				+ StringUtils.join(groupedContacts.keySet().toArray(), "','")
				+ "'";
	}
	
	public GroupService getGroupService() {
		return groupService;
	}

	public void setGroupService(GroupService groupService) {
		this.groupService = groupService;
	}

	public ContactService getContactService() {
		return contactService;
	}

	public void setContactService(ContactService contactService) {
		this.contactService = contactService;
	}

	public Map<Character, List<Contact>> getGroupedContacts() {
		return groupedContacts;
	}

	public Contact getSelectedContact() {
		return this.selectedContact;
	}

	public void setSelectedContact(Contact selectedContact) {
		this.selectedContact = selectedContact;
	}

	public String getFilterString() {
		return this.filterString;
	}

	public void setFilterString(String filterString) {
		this.filterString = filterString;
	}

	public Group getSelectedGroup() {
		return this.selectedGroup;
	}

	public void setSelectedGroup(Group selectedGroup) {
		this.selectedGroup = selectedGroup;
	}

}
